package com.ruoyi.project.mysql.connection;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.mysql.datasource.DataSourceProxy;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.SQLException;

@Slf4j
public class ConnectionProxy extends AbstractConnectionProxy{

    private String xid;

    private String beforeImg;
    private String afterImg;

    public void bind(String xid){
        this.xid = xid;
    }

    public void appendUndoLog(String beforeImg,String afterImg){
        this.beforeImg = beforeImg;
        this.afterImg = afterImg;
    }

    /**
     * Instantiates a new Abstract connection proxy.
     *
     * @param dataSourceProxy  the data source proxy
     * @param targetConnection the target connection
     */
    public ConnectionProxy(DataSourceProxy dataSourceProxy, Connection targetConnection) {
        super(dataSourceProxy, targetConnection);
    }


    @Override
    public void setAutoCommit(boolean autoCommit) throws SQLException {
        targetConnection.setAutoCommit(autoCommit);
    }

    @Override
    public void commit() throws SQLException {
        //这里可以扩展做很多事，本地事务，分布式事务的分支事务等
        if(!StringUtils.isEmpty(xid)){
            processGlobalTransactionCommit();
        }else{
            targetConnection.commit();
        }
    }

    //全局锁获取：本地事务提交前必须获得全局锁
    //全局锁释放：全局事务提交后
    private void processGlobalTransactionCommit() {
        try{
            register();
        }catch (Exception e){
            e.printStackTrace();
            log.info("注册分支事务失败：全局锁校验异常");
        }

        try{
            insertUndoLog();
            //原生sql和本条undolog一起提交本地事务
            targetConnection.commit();
            log.info("原生sql和本条undolog一起提交本地事务");
        }catch (Exception e){
            report(false);
        }
        report(true);
    }

    private void insertUndoLog() {
        //插入before after img到undo log表
        //insertToMysql(beforeImg,afterImg);
        log.info("插入undolog：前置镜像："+beforeImg+" 后置镜像："+afterImg);
    }

    private void report(boolean res) {
        //上报分支事务执行结果
        log.info("上报分支事务执行结果："+res);
    }

    private void register() throws Exception{
        //注册分支事务
        log.info("注册分支事务");
    }


    @Override
    public void rollback() throws SQLException {
        targetConnection.rollback();
    }
}
